package org.example.curriculum_design_6_16.controller;

import com.aliyun.oss.ServiceException;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.example.curriculum_design_6_16.common.auth.AccessDeniedException;
import org.example.curriculum_design_6_16.common.auth.AccountNotActiveException;
import org.example.curriculum_design_6_16.common.auth.AuthException;
import org.example.curriculum_design_6_16.common.business.ValidationException;
import org.example.curriculum_design_6_16.common.data.DuplicateDataException;
import org.example.curriculum_design_6_16.common.system.SystemException;
import org.example.curriculum_design_6_16.entity.dto.UserFormDTO;
import org.example.curriculum_design_6_16.entity.pojo.User;
import org.example.curriculum_design_6_16.entity.vo.Result;
import org.example.curriculum_design_6_16.service.*;
import org.example.curriculum_design_6_16.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.example.curriculum_design_6_16.entity.vo.UserVo;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private MailService mailService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @ApiOperation("测试")
    @GetMapping("/test")
    public Result test() {
        return Result.success(200);
    }

    @ApiOperation("发送邮箱验证码_找回密码")
    @PostMapping("/email/retrieve")
    public Result sendcode_retrieve(@RequestParam("email") String email) {
        Result result = mailService.RetrieveCodeMail(email);
        if (result.getStatus() == 200)
            return Result.success(200);
        else
            return Result.fail(result.getStatus(), result.getMsg());
    }

    @ApiOperation("发送邮箱验证码_注册")
    @PostMapping("/email/register")
    public Result sendEmail_register(@RequestBody Map<String, String> request) {
        String email = request.get("email");
        Result result = mailService.SignupCodeMail(email);
        if(result.getStatus() == 200)
            return Result.success(result.getData());
        else
            return Result.fail(result.getStatus(), result.getMsg());
    }

    @ApiOperation("用户注册接口")
    @PostMapping("/signup")
    public Result signup(@RequestBody @Validated UserFormDTO validator) {
        try {
            // 1. 验证用户数据合法性
            Result validationResult = userService.validateUserData(validator);
            if (validationResult.getStatus() == 200) {
                // 2. 创建新用户并分配默认角色
                User newUser = userService.createUserWithDefaultRole(validator);

                // 3. 生成JWT Token
                Map<String, Object> claims = new HashMap<>();
                claims.put("userId", newUser.getUserId());
                claims.put("username", newUser.getUsername());
                claims.put("roles", 2);

                String token = JwtUtil.genToken(claims);
                // 4. 保存Token到Redis
                redisService.setJwtToken(token, newUser.getEmail(), 3 * 24 * 60 * 60);

                // 5. 返回成功结果
                UserVo userVo = new UserVo();
                userVo.setJWT(token);
                userVo.setUserId(newUser.getUserId());
                userVo.setUsername(newUser.getUsername());
                userVo.setRole("2");

                return Result.success(userVo);
            }

            return validationResult;
        } catch (AccessDeniedException e) {
            throw new AccessDeniedException();
        } catch (Exception e) {
            log.error("注册失败: {}", e.getMessage(), e);
            throw new SystemException("USER_001", "注册失败，请稍后再试");
        }
    }

    @ApiOperation("用户登录接口")
    @PostMapping("/login")
    public Result login(@RequestBody @Validated UserFormDTO dto) {
        try {
            // 1. 查询并验证用户
            Result result = validateUserCredentials(dto.getEmail(), dto.getPassword());
            if(result.getStatus() == 200) {
                User user = (User) result.getData();
                // 2. 处理角色信息
                String role = userRoleService.getUserRoles(user.getUserId());

                // 3. 生成Token和用户信息
                Map<String, Object> claims = new HashMap<>();
                claims.put("userId", user.getUserId());
                claims.put("username", user.getUsername());
                claims.put("roles", role);
                String token = JwtUtil.genToken(claims);
                UserVo userVo = new UserVo();
                userVo.buildUserVo(user, role, token);

                // 4. 更新登录状态并缓存Token
                updateLoginStatus(user, token);

                return Result.success(userVo);
            }
            return result;

        } catch (AccountNotActiveException e) {
            throw e; // 认证异常直接抛出
        } catch (Exception e) {
            log.error("登录系统异常 - username/email: {}",
                    dto.getUsername() != null ? dto.getUsername() : dto.getEmail(), e);
            throw new SystemException("USER_002", "系统异常，请稍后重试");
        }
    }

    private Result validateUserCredentials(String mark, String password) {
        Result result = userService.findUserByUseridOrEmail(mark);
        User user = (User) result.getData();
        if (user == null) {
            log.warn("登录失败: 无效凭证 - username/email: {}",
                    mark != null);
            return Result.fail(410, "无效凭证");
        }
        if (!passwordEncoder.matches(password, user.getPasswordHash())) {
            return Result.fail(411, "密码错误");
        }
        if (user.getIsActive() != 1) {
            log.warn("登录失败: 账户未激活 - userId: {}", user.getUserId());
            return Result.fail(412, "账户未激活");
        }
        return Result.success(user);
    }

    private void updateLoginStatus(User user, String token) {
        try {
            userService.updateLoginInfo(user.getUserId());
            redisService.setJwtToken(token, user.getUserId(), 3 * 24 * 60 * 60);
        } catch (Exception e) {
            log.error("更新登录状态失败 - userId: {}", user.getUserId(), e);
            // 不阻断流程，但记录错误
        }
    }

    @ApiOperation("用户退出登录接口")
    @PostMapping("/logout")
    public Result logout(@RequestHeader("Authorization") String authorization) {
        try {
            // 从Authorization头中提取token
            String token = null;
            if (authorization != null && authorization.startsWith("Bearer ")) {
                token = authorization.substring(7);
            }
            
            if (token != null && !token.isEmpty()) {
                // 从Redis中删除token
                redisService.delJwtToken(token);
                log.info("用户退出登录成功，token已清除");
            }
            
            return Result.success("退出登录成功");
        } catch (Exception e) {
            log.error("退出登录失败: {}", e.getMessage(), e);
            // 即使清除token失败，也返回成功，因为前端会清除本地存储
            return Result.success("退出登录成功");
        }
    }
}
